

#include <jni.h>
//#include <string>
#include "event2/event.h"

#include "android/log.h"
#define TAG "NativeCodec"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG,__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)


#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include "event2/event.h"
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define SOCKET int
#endif

#define LINKS 1
#define IP "192.168.8.155"
#define PORT 12345


extern "C"{
int links = 0;

struct Header
{
	int size;
	int version;
	int seq;
	int event;
	int code;
	int cmd;
};

struct Login
{
	struct Header header;
	int busiID;
	char sign[32];
};

struct event_base* base = NULL;
struct event* myEvents[LINKS][2];
SOCKET sock[LINKS];
struct sockaddr_in sockAddr;
struct timeval tv;
struct Login login;
struct Header heartBeat;

void recvCB(int sock, short events, void* arg)
{
	int num = (int)(intptr_t)arg;
	char buff[1024] = { 0 };
	int len = recv(sock, buff, sizeof(buff), 0);
	if (len > 0)
	{
		//printf("recv%d,links%d:%s\n", num, links,buff);
		LOGI("recv%d,links%d:%s\n", num, links, buff);
	}
	else
	{
		struct sockaddr_in temp;
		int slen = sizeof(struct sockaddr);
		getsockname(sock, (struct sockaddr*)&temp, &slen);
		//printf("%d\n", ntohs(temp.sin_port));
		LOGI("%d\n", ntohs(temp.sin_port));
		if (len == 0)
		{
			//printf("recv%d is zero.\n",num);
			LOGI("recv%d is zero.\n", num);

		}
		else
		{
			//perror("recv");
			LOGE("recv");
		}
		--links;
		event_del(myEvents[num][0]);
		event_del(myEvents[num][1]);
	}
}

void heartBeatCB(int sock, short events, void* arg)
{
	int num = (int)(intptr_t)arg;
	send(sock, &heartBeat, sizeof(heartBeat), 0);
	//printf("heartBeat%d\n",num);
	LOGI("heartBeat%d\n", num);
	event_add(myEvents[num][1], &tv);
}

void log_cb(int severity,const char *msg)
{
	switch (severity)
	{
		case _EVENT_LOG_DEBUG:
			LOGI("DEBUG:%s\n", msg);
			break;
		case _EVENT_LOG_MSG:
			LOGI("MSG:%s\n", msg);
			break;
		case _EVENT_LOG_WARN:
			LOGI("WARN:%s\n", msg);
			break;
		case _EVENT_LOG_ERR:
			LOGI("ERR:%s\n", msg);
			break;
		default:
			LOGI("?:%s\n", msg);
			break;
	}
}

int func()
{
#ifdef _WIN32
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2,2),&wsaData);
	sockAddr.sin_addr.S_un.S_addr = inet_addr(IP);
#else
	sockAddr.sin_addr.s_addr = inet_addr(IP);
#endif
	sockAddr.sin_family = AF_INET;
	sockAddr.sin_port = htons(PORT);
	login.header.size = sizeof(struct Login);
	login.header.version = 0;
	login.header.seq = 0;
	login.header.event = 0;
	login.header.code = 0;
	login.header.cmd = 2501;
	memset(login.sign, 'x', 32);
	heartBeat.size = sizeof(struct Header);
	heartBeat.version = 0;
	heartBeat.seq = 0;
	heartBeat.event = 0;
	heartBeat.code = 0;
	heartBeat.cmd = 2502;
	tv.tv_sec = 1;
	tv.tv_usec = 0;
	event_set_log_callback(log_cb);
	while (!base)
	{
		base = event_base_new();
		//struct event_config *cfg = event_config_new();
		//base = event_base_new_with_config(cfg);
		//event_config_free(cfg);
		LOGI("base %p", base);
	}
	int i;
	for (i = 0; i < LINKS; ++i)
	{
		sock[i] = socket(AF_INET, SOCK_STREAM, 0);
		if(sock[i] < 0)
		{
			//perror("sock");
			LOGE("sock");
			return -1;
		}
		else
		{
			//printf("sock%d success.\n",i);
			LOGI("sock%d success.\n", i);
		}
		if (connect(sock[i], (struct sockaddr*)&sockAddr, sizeof(struct sockaddr)) == -1)
		{
			//perror("conn");
			LOGE("conn");
#ifdef _WIN32
			closesocket(sock[i]);
#else
			close(sock[i]);
#endif
			return -2;
		}
		else
		{
			//printf("conn%d success.\n",i);
			LOGI("conn%d success.\n", i);
		}
		login.busiID = i;
		send(sock[i],&login,sizeof(struct Login),0);
		//printf("login%d\n",i);
		LOGI("login%d\n", i);
		++links;
		myEvents[i][0] = event_new(base, sock[i], EV_READ | EV_PERSIST, recvCB, (void*)(intptr_t)i);
		LOGI("myEvents[i][0] %p", myEvents[i][0]);
		myEvents[i][1] = event_new(base, sock[i], EV_TIMEOUT, heartBeatCB, (void*)(intptr_t)i);
		LOGI("myEvents[i][1] %p", myEvents[i][1]);
		event_add(myEvents[i][0], NULL);
		event_add(myEvents[i][1], &tv);
	}
	event_base_dispatch(base);
#ifdef _WIN32
	WSACleanup();
#endif
	for (i = 0; i < LINKS; ++i)
	{
		int j;
		for (j = 0; j < 2; ++j)
		{
			event_free(myEvents[i][j]);
		}
	}
	event_base_free(base);
	return 0;
}




void event_log_callback (int errcode,const char* msg){
    LOGI("event_log_callback [%d]%s",errcode,msg);
}
jstring
Java_gl_libeventdemo_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
//    std::string hello = "Hello from C++";
    const char* hello = "Hello from C++";
    event_base *base = event_base_new();
    event_log_cb (event_log_callback);
    LOGI("eventbase %p",base);
    LOGI("hello %s",hello);
    LOGI("login gataway %d", func());
    return env->NewStringUTF(hello);
}
}


